package edu.ucsb.cs56.W12.chatclient.model;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;

import edu.ucsb.cs56.W12.chatclient.controller.ClientController;

/**
 * Client class represents a client who can connect/disconnect to the server 
 * and chat with other people on the server 
 * @author Peng Wang and Andro Stotts
 * @version 0.1
 */
public class Client {
	private String name;
	private String serverIp;
	private String clientIp;
	private static Client client;
	private Socket mySocket;
	private DataOutputStream dos;
	private DataInputStream dis;
	private ClientController controller;
	private boolean isConnected;
	
	/**
	 * Default constructor
	 */
	private Client(){
		name = "";
		serverIp = "";
		clientIp = "";
		mySocket = null;
		dos = null;
		dis = null;
		isConnected = false;
	}
	
	/**
	 * getClient method is used for get a client object
	 * @return instance of Client
	 */
	public static Client getClient(){
		if(client == null)
			client = new Client();
		return client;
	}
	
	/**
	 * setName method is used for setting user's name property
	 * @param name the username
	 */
	public void setName(String name){
		this.name = name;
	}
	
	/**
	 * getName method is used for getting the name property of a Client object
	 * @return the user's name
	 */
	public String getName(){
		return name;
	}
	
	/**
	 * setServerIp method is used for setting the IP address which the client is connecting 
	 * @param serverIp the IP address of the server
	 */
	public void setServerIp(String serverIp){
		this.serverIp = serverIp;
	}
	
	/**
	 * getServerIp returns the server IP address which the client is connecting
	 * @return the server's IP address
	 */
	public String getServerIp(){
		return serverIp;
	}
	
	/**
	 * setClientIp is used for setting the client IP address 
	 * @param clientIp the IP address of the client
	 */
	public void setClientIp(String clientIp){
		this.clientIp = clientIp;
	}
	
	/**
	 * get the client IP address
	 * @return the clientIp address
	 */
	public String getClientIp(){
		return clientIp;
	}
	
	/**
	 * ConnectServer method takes server IP address parameter to connect the specific
	 * server and takes client name and password in order to check login authority 
	 * @param ip the ip address of the server
	 * @param name the username
	 */
	public void connectServer(String ip, String name){
		this.setName(name);
		this.setServerIp(ip);
		controller = ClientController.getController();
		try {
			//create a new socket and connect to IP address at socket 8888
			//and create data output and input stream
			mySocket = new Socket(serverIp, 8888);			
			dos = new DataOutputStream(mySocket.getOutputStream());
			dis = new DataInputStream(mySocket.getInputStream());
			controller.displayMsg(name + " has connected to the server at " + serverIp + '\n');

			//set connection flag to true and create a new thread to run recieving message
			isConnected = true;
			new Thread(new RecieveMsg()).start();
		} catch (IOException e) {
			controller.displayMsg("Connected to the server fialed, please try again later.\n");
		}
	}
	
	/**
	 * disconnectServer method is used for disconnecting the client with the server (non-functional)
	 */
	public void disconnectServer(){
		//not currently functional	
	}
	
	/**
	 * sendMsg is the method that used for send a text message to the server
	 * @param s s is the text message to send to the server
	 */
	public void sendMsg(String s){
		try {
			dos.writeUTF(name + " : " + s);
		} catch (IOException e) {
			controller.displayMsg("Error occured when sending message to the server");
		}
	}
	
	/**
	 * RecieveMsg class represent a seperate thread that constantly recieving message from the server
	 * @author Peng Wang and Andro Stotts
	 * @version 0.1
	 */
	class RecieveMsg implements Runnable{
		/**
		 * run is the method to receive messages from the server
		 */
		public void run() {
			try{
				while(isConnected){
					String str = dis.readUTF();
					controller.displayMsg(str + '\n');
				}
			} catch (SocketException e){
				controller.displayMsg(name + " has quit the program.");
			}
			catch(IOException e){
				e.printStackTrace();
			}
		}		
	}
}
